%{
    #include <streambuf>
    #include <ostream>
    #include <istream>
    #include <sstream>
%}

%import StdAlloc.i
%import StdIos.i
%import StdString.i

%define WARP_STREAM_TYPE(CONST ,TYPE)
%typemap(cstype) TYPE*, TYPE&, CONST TYPE*, CONST TYPE& "global::System.IntPtr"
%typemap(imtype, out="global::System.IntPtr") TYPE*, TYPE&, CONST TYPE*, CONST TYPE& "global::System.IntPtr"
%typemap(csin) TYPE*, TYPE&, CONST TYPE*, CONST TYPE& "$csinput"
%typemap(csout, excode=SWIGEXCODE) TYPE*, TYPE&, CONST TYPE*, CONST TYPE& {
    global::System.IntPtr cPtr = $imcall;
    return cPtr;
}
%enddef

namespace std {

    template<typename _CharT, typename _Traits = char_traits<_CharT>>
    class basic_streambuf {
        public:
            typedef _CharT char_type;
            typedef _Traits traits_type;
            typedef typename traits_type::int_type int_type;
            typedef typename traits_type::pos_type pos_type;
            typedef typename traits_type::off_type off_type;
            WARP_STREAM_TYPE(const, char_type)
        public:
            basic_streambuf() = delete;
            locale pubimbue(const locale &__loc);
            locale getloc() const;
            basic_streambuf<_CharT, _Traits>* pubsetbuf(char_type* __s, streamsize __n);
            pos_type pubseekoff(off_type __off, ios_base::seekdir __way, 
                ios_base::openmode __mode = std::ios_base::in | std::ios_base::out);
            pos_type pubseekpos(pos_type __sp,
                ios_base::openmode __mode = std::ios_base::in | std::ios_base::out);
            int pubsync();
            streamsize in_avail();
            int_type snextc();
            int_type sbumpc();
            int_type sgetc();
            streamsize sgetn(char_type* __s, streamsize __n);
            int_type sputbackc(char_type __c);
            int_type sungetc();
            int_type sputc(char_type __c);
            streamsize sputn(const char_type* __s, streamsize __n);
    };

    template<typename _CharT, typename _Traits = char_traits<_CharT>,
    typename _Alloc = allocator<_CharT>>
    class basic_stringbuf : public basic_streambuf<_CharT, _Traits> {
        public:
            typedef _CharT char_type;
            typedef _Traits traits_type;
            typedef _Alloc allocator_type;
            typedef typename traits_type::int_type int_type;
            typedef typename traits_type::pos_type pos_type;
            typedef typename traits_type::off_type off_type;
            WARP_STREAM_TYPE(const, char_type)
        public:
            explicit basic_stringbuf(ios_base::openmode __mode = ios_base::in | ios_base::out);
            explicit basic_stringbuf(const std::basic_string<_CharT, _Traits, _Alloc>& __str, 
                ios_base::openmode __mode = ios_base::in | ios_base::out);
            std::basic_string<_CharT, _Traits, _Alloc> str() const;
            void str(const std::basic_string<_CharT, _Traits, _Alloc>& __s);
    };

    template<typename _CharT, typename _Traits = char_traits<_CharT>>
    class basic_ostream : virtual public basic_ios<_CharT, _Traits> {
        public:
            typedef _CharT char_type;
            typedef typename _Traits::int_type int_type;
            typedef typename _Traits::pos_type pos_type;
            typedef typename _Traits::off_type off_type;
            typedef _Traits traits_type;
            WARP_STREAM_TYPE(const, char_type)

            explicit basic_ostream(basic_streambuf<_CharT, _Traits>* __sb);
            basic_ostream<_CharT, _Traits>& put(char_type __c);
            basic_ostream<_CharT, _Traits>& write(const char_type* __s, streamsize __n);
            basic_ostream<_CharT, _Traits>&  flush();
            pos_type tellp();
            basic_ostream<_CharT, _Traits>& seekp(pos_type pos);
            basic_ostream<_CharT, _Traits>& seekp(off_type off, ios_base::seekdir dir);
    };

    template<typename _CharT, typename _Traits = char_traits<_CharT>>
    class basic_istream : virtual public basic_ios<_CharT, _Traits> {
        public:
            typedef _CharT char_type;
            typedef typename _Traits::int_type int_type;
            typedef typename _Traits::pos_type pos_type;
            typedef typename _Traits::off_type off_type;
            typedef _Traits traits_type;
            WARP_STREAM_TYPE(const, char_type)

            explicit basic_istream(basic_streambuf<_CharT, _Traits>* __sb);
            inline streamsize gcount(void) const;
            int_type get(void);
            basic_istream<_CharT, _Traits>& get(char_type& __c);
            basic_istream<_CharT, _Traits>& get(char_type* __s, streamsize __n, char_type __delim);
            inline basic_istream<_CharT, _Traits>& get(char_type* __s, streamsize __n);
            basic_istream<_CharT, _Traits>& get(basic_streambuf<_CharT, _Traits>& __sb, char_type __delim);
            inline basic_istream<_CharT, _Traits>& get(basic_streambuf<_CharT, _Traits>& __sb);
            basic_istream<_CharT, _Traits>& getline(char_type* __s, streamsize __n, char_type __delim);
            inline basic_istream<_CharT, _Traits>& getline(char_type* __s, streamsize __n);
            basic_istream<_CharT, _Traits>& ignore(streamsize __n = 1, int_type __delim = _Traits::eof());
            int_type peek(void);
            basic_istream<_CharT, _Traits>& read(char_type* __s, streamsize __n);
            streamsize readsome(char_type* __s, streamsize __n);
            basic_istream<_CharT, _Traits>& putback(char_type __c);
            basic_istream<_CharT, _Traits>& unget(void);
            int sync(void);
            pos_type tellg(void);
            basic_istream<_CharT, _Traits>& seekg(pos_type pos);
            basic_istream<_CharT, _Traits>& seekg(off_type pos, ios_base::seekdir dir);
    };

    template<typename _CharT, typename _Traits = char_traits<_CharT>>
    class basic_iostream {
        public:
            typedef _CharT char_type;
            typedef typename _Traits::int_type int_type;
            typedef typename _Traits::pos_type pos_type;
            typedef typename _Traits::off_type off_type;
            typedef _Traits  traits_type;
            WARP_STREAM_TYPE(const, char_type)

            explicit basic_iostream(basic_streambuf<_CharT, _Traits>* __sb);
            basic_ostream<_CharT, _Traits>& put(char_type __c);
            basic_ostream<_CharT, _Traits>& write(const char_type* __s, streamsize __n);
            basic_ostream<_CharT, _Traits>&  flush();
            pos_type tellp();
            basic_ostream<_CharT, _Traits>& seekp(pos_type pos);
            basic_ostream<_CharT, _Traits>& seekp(off_type off, ios_base::seekdir dir);
            inline streamsize gcount(void) const;
            int_type get(void);
            basic_istream<_CharT, _Traits>& get(char_type& __c);
            basic_istream<_CharT, _Traits>& get(char_type* __s, streamsize __n, char_type __delim);
            inline basic_istream<_CharT, _Traits>& get(char_type* __s, streamsize __n);
            basic_istream<_CharT, _Traits>& get(basic_streambuf<_CharT, _Traits>& __sb, char_type __delim);
            inline basic_istream<_CharT, _Traits>& get(basic_streambuf<_CharT, _Traits>& __sb);
            basic_istream<_CharT, _Traits>& getline(char_type* __s, streamsize __n, char_type __delim);
            inline basic_istream<_CharT, _Traits>& getline(char_type* __s, streamsize __n);
            basic_istream<_CharT, _Traits>& ignore(streamsize __n = 1, int_type __delim = _Traits::eof());
            int_type peek(void);
            basic_istream<_CharT, _Traits>& read(char_type* __s, streamsize __n);
            streamsize readsome(char_type* __s, streamsize __n);
            basic_istream<_CharT, _Traits>& putback(char_type __c);
            basic_istream<_CharT, _Traits>& unget(void);
            int sync(void);
            pos_type tellg(void);
            basic_istream<_CharT, _Traits>& seekg(pos_type pos);
            basic_istream<_CharT, _Traits>& seekg(off_type pos, ios_base::seekdir dir);
    };

    template<typename _CharT, typename _Traits = char_traits<_CharT>, 
    typename _Alloc = allocator<_CharT>>
    class basic_stringstream : public basic_iostream<_CharT, _Traits> {
        public:
            typedef _CharT char_type;
            typedef _Traits traits_type;
            typedef _Alloc allocator_type;
            typedef typename traits_type::int_type int_type;
            typedef typename traits_type::pos_type pos_type;
            typedef typename traits_type::off_type off_type;
            explicit basic_stringstream(ios_base::openmode __m = ios_base::out | ios_base::in);
            explicit basic_stringstream(const std::basic_string<_CharT, _Traits, _Alloc>& __str, 
                ios_base::openmode __m = ios_base::out | ios_base::in);
            basic_stringbuf<_CharT, _Traits, _Alloc>* rdbuf() const;
            std::basic_string<_CharT, _Traits, _Alloc> str() const;
            void str(const std::basic_string<_CharT, _Traits, _Alloc>& __s);
    };
}

namespace std {
    typedef basic_streambuf<char> streambuf;
    typedef basic_ostream<char> ostream;
    typedef basic_istream<char> istream;
    typedef basic_iostream<char> iostream;
    
    typedef basic_stringbuf<char> stringbuf;
    typedef basic_stringstream<char> stringstream;

    %template(streambuf) basic_streambuf<char>;
    %template(ostream) basic_ostream<char>;
    %template(istream) basic_istream<char>;
    %template(iostream) basic_iostream<char>;

    %template(stringbuf) basic_stringbuf<char>;
    %template(stringstream)  basic_stringstream<char>;
}